iT邦幫忙

2024 iThome 鐵人賽

DAY 3
0
Software Development

RISC-V 與處理器之架構學習及應用系列 第 3

[Day03] RISC-V Instructions (1/3)

  • 分享至 

  • xImage
  •  

一、計算機是如何從基礎層面建構起來

  1. 任何我們寫的 code,最終都需要在電路上執行,才能發揮實際作用。而電路級別的編程非常受限,因為每個基本元件的行為必須被預先定義,無法靈活地處理不同的操作需求。
  2. 程式語言讓我們能使用抽象的語言來解決問題,而不是直接處理電路層級的細節。透過創建一個通用的電路(CPU),它可以執行一系列儲存為二進制數據的指令,程式語言讓這些指令更容易編寫和管理。

二、CPU、ISA、Assembly Language

  1. 設計 CPU 時需要決定 Instruction Set
    • 由於 CPU 建成後不會再更改,因此在設計 CPU 時,必須決定 CPU 支援的 Instruction Set。
    • 這些指令需要能被翻譯成二進制格式以供 CPU 執行。
  2. ISA, Instruction Set Architectures(指令集架構)
    • 不同的 CPU 實現不同的 ISA。
    • ISA 定義了 CPU 可以執行哪些操作,以及這些操作如何用二進制形式表達。
  3. Assembly Language
    • 定義指令集的程式語言被稱為組合語言,組合語言直接與硬體溝通,讓程式開發者能用接近 CPU 的語言編寫程式。
    • 常見的組合語言包括:ARM(行動設備使用)、Intel x86(如 Core i9, i7, i5, i3)、IBM/Motorola PowerPC(老款 Mac 使用)、MIPS、LoongArch、RISC-V 等。

三、ISA 和 RISC

  1. 早期的 ISA 設計趨勢
    • 早期的 ISA 設計趨勢是為了增加 CPU 的指令數量,讓 CPU 可以執行更複雜的操作。
    • 例如,VAX 架構就有一個用於多項式相乘的指令,展示了早期 ISA 的複雜性。
  2. RISC 的理念
    • RISC 的核心思想是保持指令集小且簡單。
    • 複雜的操作應該交由軟體來組合簡單的指令來完成,而不是由硬體直接支持複雜的指令。
    • 簡單的 CPU 更容易進行改進(有助於更快速的開發),而且通常比複雜的 CPU 更快,因為我們經常受限於我們所實現的最慢的指令。
    • 與 x86 相比,RISC-V 更加簡單。x86 是 CISC 架構,使用 Huffman 編碼來壓縮指令,而 RISC-V 的指令更加直觀和統一。

四、RISC-V 系統的整體架構及其運作方式

  1. RISC-V 系統的兩個主要部分
    • CPU:負責執行計算。
    • 主記憶體:負責長期數據存儲。
  2. CPU 可以通過 registers 儲存少量的數據。registers 是 CPU 內部的高速存儲單元,用於快速存取和操作數據。

五、CPU

https://ithelp.ithome.com.tw/upload/images/20240917/20156517FZNHgsOrgq.jpg

  1. 處理器的主要組件
    • 控制單元(Control):管理和協調處理器的操作,包括從記憶體獲取指令、解碼和執行。
    • 數據通路(Datapath):包含 registers、PC(程式計數器)、ALU 等,用於執行實際的數據處理和計算操作。
  2. registers 的位置
    • registers 位於處理器內部的數據通路(Datapath)部分。
  3. Memory
    • 記憶體儲存 Program 和 Data。
    • 處理器透過地址總線和數據總線與記憶體進行讀寫操作。
  4. I/O-Memory Interfaces
    • 負責處理器與外部設備(如輸入設備和輸出設備)之間的數據交換。

六、registers

  1. registers 的功能
    • registers 是 CPU 中的硬體元件,專門用來儲存少量數據。
    • 每個 registers 在 32 位系統中儲存 32 位元的數據,在 64 位系統中儲存 64 位元的數據。
    • 本學習文章集中於 RV32,使用 32 位元的 registers。
  2. 硬體限制
    • registers 是硬體元件,一旦設計完成,就無法變更 registers 的數量。
    • 在 RISC-V 架構中,有 32 個整數 registers 可供使用。
  3. registers 的編號
    • registers 從 0 到 31 編號,即 x0 到 x31。
    • 每個 registers 的功能由編號決定,並遵循特定使用慣例。
  4. 特殊的 x0 registers
    • x0 是一個特殊 registers,總是儲存值 0,寫入 x0 的任何操作都會被忽略。
    • 因此,真正可用於數據存儲的 registers 有 31 個(x1 到 x31)。
  5. 其他 registers 的行為
    • 除 x0 之外的 31 個暫存器在行為上是相同的,主要區別在於使用上的慣例。
    • 未來將對每個 registers 命名,以提示其在不同應用中的使用規則。

七、RISC-V 指令的基本格式

  1. 指令格式
    • 每一行 RISC-V 代碼代表一條簡單指令,執行在暫存器上的操作。
    • 指令格式為:<指令名稱> <目的暫存器> <操作數>
    • 例如,add x5, x6, x7 表示將 x6 和 x7 中的值相加,結果儲存在 x5 中。
    • 操作數之間可以加逗號分隔,如 add x5, x6, x7,但這並非必須。
  2. 註解
    • 註解用 # 開頭,# 後面的內容會被忽略,類似於 Python 的註解語法。
    • 註解在 RISC-V 編程中特別重要,因為它們能幫助理解和排除錯誤。
    • 在高級語言中,變量名稱可以幫助代碼自我說明。但在 RISC-V 中,沒有變量名稱,只有暫存器編號。
    • 因此,如果不添加註解,RISC-V 代碼幾乎無法進行正確的調試和理解。

八、Addition and Subtraction of Integers

介紹了 RISC-V 中整數的加法和減法指令,並將其與 C 語言中的運算做比較:

  1. 整數加法(Addition)
    • RISC-V 指令格式:add x1, x2, x3
      • 這條指令表示將暫存器 x2x3 中的值相加,結果存入 x1 中。
    • 對應的 C 語言表達:a = b + c
      • 其中,a 對應 x1b 對應 x2c 對應 x3
  2. 整數減法(Subtraction)
    • RISC-V 指令格式:sub x3, x4, x5
      • 這條指令表示將暫存器 x4 中的值減去 x5 中的值,結果存入 x3 中。
    • 對應的 C 語言表達:d = e - f
      • 其中,d 對應 x3e 對應 x4f 對應 x5
  3. C 語言的轉換:
    • 如果有 C 語言的表達式 a = b + c + d - e;,需要將其分解為多個 RISC-V 指令來實現:
      add x10, x1, x2  # 將 b + c 存入 x10
      add x10, x10, x3 # 將之前的結果加上 d
      sub x10, x10, x4 # 最後將結果減去 e
      
    • 每條指令的註解會用 # 符號,註解部分用於說明該指令的作用。
  4. 使用臨時暫存器:
    • 在一些複雜的計算中,例如 (g + h) - (i + j),會使用臨時暫存器來保存中間結果:
      add x5, x20, x21  # g + h 存入 x5
      add x6, x22, x23  # i + j 存入 x6
      sub x19, x5, x6   # (g + h) - (i + j) 存入 x19
      
    • 使用暫存器時要注意不要覆蓋重要的數據,因此通常會保留一些暫存器專門用於中間計算。
  5. RISC-V 指令特性:
    • RISC-V 指令操作簡單且一致,每一條指令都執行一個基本的操作。
    • RISC-V 沒有變數名稱的概念,因此注釋 (comments) 變得尤為重要,方便後續調試和理解程式碼。
    • RISC-V 中的程式碼若沒有加註解,很難進行調試,因此在寫程式碼時務必加上註解。

九、Pseudo-instructions

  1. Pseudo-instructions 的目的
    • 在 ISA 中,每個指令都需要一些電路來支持。因此,我們希望盡可能減少 ISA 中的指令數量,以簡化硬件設計。
  2. Pseudo-instructions 的使用
    • 有些指令常用,可以通過其他指令組合來實現。為了簡化編程,這些指令被設計為偽指令,即快捷的表示方式。
    • 偽指令由編譯器(assembler)在早期階段轉換成常規的指令。
  3. Pseudo-instructions 範例
    • Pseudo-instructions mv x5, x6 表示將 x6 的值設置到 x5 中。
    • 對應的正常指令為 add x5, x6, x0,這條指令將 x6 的值與 x0(恆為 0)相加,並存入 x5

十、 RISC-V 中的 Immediates(立即數)

介紹了 RISC-V 中的 Immediates 的概念和使用方法:

  1. Immediates 數字常數
    • 是直接在指令中使用的數字常數,經常出現在程式碼中,因此有專門的指令來處理這些常數。
  2. Add Immediate (加法)
    • 語法範例:addi x3, x4, 10 (在 RISC-V 中)
    • 等效於 C 語言中的:f = g + 10
    • 這裡的 RISC-V 暫存器 x3x4 對應到 C 中的變數 fg
    • 語法與加法指令類似,但最後一個參數是一個數字而非暫存器。
  3. 沒有減法立即數指令的原因
    • RISC-V 沒有 Subtract Immediate 指令的原因
      • RISC-V 提供了加法和減法指令,但沒有減法立即數指令(subi)。
      • 這是因為 RISC-V 希望將操作類型的數量控制到最低,任何可以簡化為更基本操作的指令都不會包括在內。
  4. 操作的簡化
    • 例如:addi ..., -X 等效於 subi ..., X,所以不需要額外的 subi 指令。
    • 範例:addi x3, x4, -10 (在 RISC-V 中)
    • 等效於 C 語言中的:f = g - 10
    • 這裡的 RISC-V 暫存器 x3x4 仍然對應到 C 中的變數 fg

十一、 RISC-V 中的 Register Zero (x0)

  1. 特殊的 Immediates:0
    • 在程式碼中,數字 0 是非常常見的 Immediates。因此,RISC-V 將 register x0 硬體化為固定值 0。
  2. x0 register 的硬體定義
    • register x0 永遠是 0,因此任何寫入 x0 的操作都會被忽略。
    • 例如,指令 add x3, x4, x0x4 的值加上 0 並存入 x3,這等效於 C 語言中的 f = g,其中 f 對應於 x3g 對應於 x4
  3. 特性
    • 因為 x0 硬體上固定為 0,像 add x0, x3, x4 這樣的指令將不會執行任何有效操作,因為結果永遠是寫入 x0,而 x0 不會改變。

上一篇
[Day02] 現代處理器架構與效能最佳化技術
下一篇
[Day04] RISC-V Instructions (2/3)
系列文
RISC-V 與處理器之架構學習及應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言